package com.dragon.modules.yuegou.service.impl.marketing;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.exception.DragonException;
import com.dragon.common.web.PageRequest;
import com.dragon.modules.yuegou.entity.busd.DistrictEntity;
import com.dragon.modules.yuegou.entity.marketing.AdvertisementEntity;
import com.dragon.modules.yuegou.enums.code.BusinessCode;
import com.dragon.modules.yuegou.enums.code.MarketingCode;
import com.dragon.modules.yuegou.enums.marketing.AdvertisementAdType;
import com.dragon.modules.yuegou.enums.marketing.AdvertisementIntervalUnit;
import com.dragon.modules.yuegou.enums.marketing.AdvertisementStatus;
import com.dragon.modules.yuegou.enums.marketing.AdvertisementType;
import com.dragon.modules.yuegou.mapper.marketing.AdvertisementMapper;
import com.dragon.modules.yuegou.model.marketing.Advertisement;
import com.dragon.modules.yuegou.query.marketing.AdvertisementQuery;
import com.dragon.modules.yuegou.service.busd.DistrictService;
import com.dragon.modules.yuegou.service.marketing.AdvertisementService;
import com.dragon.modules.yuegou.utils.PageToResultUtils;
import com.dragon.modules.yuegou.web.Check;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 广告信息表 服务实现
 *
 * @author pbuilder generated
 * @date 2019-11-19 15:55:02
 * @version 2.0
 */
@Service("mktAdvertisementService")
public class AdvertisementServiceImpl
		extends ServiceImpl<AdvertisementMapper, AdvertisementEntity>
		implements AdvertisementService {

	/**
	 * 广告展示缓存名称
	 */
	protected static final String ADVERTISEMENT_SHOW_TIME_CACHE_NAME = "advertisementCache";
	
	private Cache advertisementCache;
	
	@Autowired
	public void setCacheManager(CacheManager cacheManager) {
		this.advertisementCache = cacheManager.getCache(ADVERTISEMENT_SHOW_TIME_CACHE_NAME);
	}
	
	@Autowired
	private DistrictService districtService;

	@Override
	public IPage<Advertisement> search(PageRequest page, AdvertisementQuery query) {
		query.setDel(false);
		QueryWrapper<AdvertisementEntity> wrapper = query.toQueryWrapper();
		wrapper.orderByAsc(Advertisement.COL_SORT_NO);
		wrapper.orderByDesc(Advertisement.COL_CREATED_TIME);
		return page(PageToResultUtils.resultToPage(page), wrapper);
	}

	@Override
	public void editStatus(String id, AdvertisementStatus status) {
		Check.notEmpty(id, "广告ID不能为空");
		Check.notNull(status, "广告状态不能为空");
		AdvertisementEntity advertisement = getById(id);
		if (advertisement == null) {
			throw new DragonException(MarketingCode.NOT_FIND_ADV);
		}
		// 判断商圈上架数量限制
		if (status == AdvertisementStatus.NORMAL) {
			if(advertisement.getAdType()==AdvertisementAdType.BANNER){
				checkBannerMaxNum(advertisement.getBusdId(), advertisement.getId());
			}else if (advertisement.getAdType()==AdvertisementAdType.BRAND){
				checkBrandMaxNum(advertisement.getBusdId());
			}
		}
		advertisement.setId(id);
		advertisement.setStatus(status);
		baseMapper.updateById(advertisement);
	}

	@Override
	@Transactional
	public void saveAdvertisement(Advertisement advertisement){
		Check.notNull(advertisement.getBusdId(), BusinessCode.BUSDID_NOTNULL.getMessage());
		Check.notEmpty(advertisement.getName(),"名称不能为空");
		Check.notNull(advertisement.getAdType(),"广告类型不能为空");
		Check.notNull(advertisement.getType(),"跳转类型不能为空");
		if(advertisement.getType().getCode().equals(AdvertisementType.LINK.getCode())) {
			Check.notEmpty(advertisement.getUrl(), "链接地址不能为空");
		}else if(advertisement.getType().getCode().equals(AdvertisementType.GOODS.getCode()) || 
				advertisement.getType().getCode().equals(AdvertisementType.POINTDETAIL.getCode())|| 
				advertisement.getType().getCode().equals(AdvertisementType.PACKAGE.getCode())){
			Check.notNull(advertisement.getSpuId(), "商品不能为空");
		}else if(advertisement.getType().getCode().equals(AdvertisementType.ASSISTANCE.getCode()) ||
				advertisement.getType().getCode().equals(AdvertisementType.SECKILL.getCode())|| 
				advertisement.getType().getCode().equals(AdvertisementType.DISCOUNT.getCode())|| 
				advertisement.getType().getCode().equals(AdvertisementType.GROUPON.getCode())|| 
				advertisement.getType().getCode().equals(AdvertisementType.COUPON.getCode())||
				advertisement.getType().getCode().equals(AdvertisementType.ONLINELOT.getCode())){
			Check.notNull(advertisement.getObjId(), advertisement.getType().getAlias()+"ID不能为空");
		}
		if(StringUtils.isEmpty(advertisement.getId())){
			advertisement.setDel(false);
			advertisement.setStatus(AdvertisementStatus.DISABLE);
			baseMapper.insert(advertisement);
		}else{
			baseMapper.updateById(advertisement);
		}
		if(advertisement.getStatus() == AdvertisementStatus.NORMAL){
			if(advertisement.getAdType()==AdvertisementAdType.BANNER){
				checkBannerMaxNum(advertisement.getBusdId(), advertisement.getId());
			}else if (advertisement.getAdType()==AdvertisementAdType.BRAND){
				checkBrandMaxNum(advertisement.getBusdId());
			}
		}
	}

	/**
	 * 根据商圈许可限制可上架广告数量
	 * @param busdId
	 */
	private void checkBannerMaxNum(String busdId, String advertisementId) {
		Check.notEmpty(busdId, BusinessCode.BUSDID_NOTNULL.getMessage());
		// 查询商圈许可上架的数量
		DistrictEntity district = districtService.getById(busdId);
		if (district == null || district.getBannerQuantity() == null) {
			throw new DragonException(MarketingCode.BANNER_QUANTITY_IS_NULL);
		}
		// 查询商圈上架广告数量
		AdvertisementQuery query = new AdvertisementQuery();
		query.setStatus(AdvertisementStatus.NORMAL);
		query.setDel(false);
		query.setBusdId(busdId);
		if(StringUtils.isNotEmpty(advertisementId)){
			query.id().notIn(Arrays.asList(advertisementId));
		}
		// 查询商圈上架BANNER数量
		query.setAdType(AdvertisementAdType.BANNER);
		if (count(query.toQueryWrapper()) >= district.getBannerQuantity()) {
			throw new DragonException(MarketingCode.BANNER_QUANTITY_LIMITED);
		}
	}
	
	/**
	 * 根据商圈许可限制可上架广告数量
	 * @param busdId
	 */
	private void checkBrandMaxNum(String busdId) {
		Check.notEmpty(busdId, BusinessCode.BUSDID_NOTNULL.getMessage());
		// 查询商圈上架广告数量
		AdvertisementQuery query = new AdvertisementQuery();
		query.setStatus(AdvertisementStatus.NORMAL);
		query.setDel(false);
		query.setBusdId(busdId);
		// 查询商圈上架BRAND数量
		query.setAdType(AdvertisementAdType.BRAND);
		if (count(query.toQueryWrapper()) >= 1) {
			throw new DragonException(MarketingCode.BANNER_QUANTITY_LIMITED);
		}
	}

	@Override
	public void editSort(String id,Integer sortNo){
		Check.notNull(id, MarketingCode.ID_NOTNULL.getMessage());
		Check.digits(sortNo,9,0,"排序必须是正整数");
		Check.positive(sortNo,"排序必须是正整数");
		Advertisement advertisement = new Advertisement();
		advertisement.setId(id);
		advertisement.setSortNo(sortNo);
		baseMapper.updateById(advertisement);
	}

	@Override
	public List<Advertisement> list(String busdId, AdvertisementAdType adType) {
		return this.list(busdId,adType,null);
	}

	@Override
	public List<Advertisement> list(String busdId, AdvertisementAdType adType ,AdvertisementStatus advertisementStatus) {
		Check.notNull(busdId, BusinessCode.BUSDID_NOTNULL.getMessage());
		AdvertisementQuery query = new AdvertisementQuery();
		query.setBusdId(busdId);
		query.setAdType(adType);
		if (adType == AdvertisementAdType.BANNER || adType == AdvertisementAdType.ALERT || adType == AdvertisementAdType.LIVE){
			query.setBeginTime(LocalDateTime.now());
			query.setEndTime(LocalDateTime.now());
		}
		if (advertisementStatus!=null){
			query.setStatus(advertisementStatus);
		}
		return baseMapper.listByType(query);
	}
	
	@Override
	public Advertisement indexAlertAdv(String busdId, String openId) {
		Check.notNull(busdId, BusinessCode.BUSDID_NOTNULL.getMessage());
		Check.notNull(openId, "openId不能为空");
		AdvertisementQuery query = new AdvertisementQuery();
		query.setBusdId(busdId);
		query.setAdType(AdvertisementAdType.ALERT);
		query.setBeginTime(LocalDateTime.now());
		query.setEndTime(LocalDateTime.now());
		query.setStatus(AdvertisementStatus.NORMAL);
		List<Advertisement> advertisementList = baseMapper.listByType(query);
		Advertisement advertisement = CollectionUtils.isEmpty(advertisementList) ? null : advertisementList.get(0);
		String cacheId = "P"+busdId + openId;
		if (advertisement != null && isAdvShowTime(cacheId, advertisement)) {
			return advertisement;
		}
		return null;
	}

	@Override
	public void updateAdvertisementStatus(String busdId) {
		AdvertisementQuery query = new AdvertisementQuery();
		if (StringUtils.isNotBlank(busdId)){
			query.setBusdId(busdId);
		}
		query.setDel(false);
		query.setEndLimit(true);
		List<AdvertisementEntity> list = list(query.toQueryWrapper());
		if (CollectionUtils.isNotEmpty(list)){
			list.stream().forEach(advertisement -> {
				if (advertisement.getStatus() == AdvertisementStatus.NORMAL && advertisement.getEndTime().compareTo(LocalDateTime.now()) <= 0){
					advertisement.setStatus(AdvertisementStatus.DISABLE);
					baseMapper.updateById(advertisement);
				}
				if (advertisement.getStatus() == AdvertisementStatus.DISABLE && advertisement.getBeginTime().compareTo(LocalDateTime.now()) <= 0){
					advertisement.setStatus(AdvertisementStatus.NORMAL);
					baseMapper.updateById(advertisement);
				}
			});
		}
	}

	@Override
	public Advertisement getAdvertisement(String busdId, Integer adType) {
		Check.notNull(busdId, BusinessCode.BUSDID_NOTNULL.getMessage());
		Check.notNull(adType, "广告类型不能为空");

		AdvertisementQuery query = new AdvertisementQuery();
		query.setBusdId(busdId);
		query.setAdType(AdvertisementAdType.from(adType));
		if (AdvertisementAdType.BANNER.getCode() == adType
				||AdvertisementAdType.ALERT.getCode() == adType
				||AdvertisementAdType.LIVE.getCode() == adType){
			query.setBeginTime(LocalDateTime.now());
			query.setEndTime(LocalDateTime.now());
		}
		query.setStatus(AdvertisementStatus.NORMAL);
		List<Advertisement> advertisementList = baseMapper.listByType(query);

		return  CollectionUtils.isEmpty(advertisementList) ? new Advertisement() : advertisementList.get(0);
	}

	/**
	 * @param cacheId 缓存ID
	 * @param interval 间隔时间
	 * @return
	 */
	private boolean isAdvShowTime(String cacheId, Advertisement interval) {
		Advertisement advertisement = advertisementCache.get(cacheId, Advertisement.class);
		// 该用户从来没有展示过
		if (advertisement == null) {
			advertisement = new Advertisement();
			advertisement.setBeginTime(LocalDateTime.now());
			advertisementCache.put(cacheId, advertisement);
			return true;
		} else {
			// 上次展示的时间
			Long minutes = Duration.between(advertisement.getBeginTime(), LocalDateTime.now()).toMinutes();
			Integer hourMinutes = (interval.getInterval() * 60);
			if (interval.getIntervalUnit() == AdvertisementIntervalUnit.MINUTE){
				hourMinutes = interval.getInterval();
			}
			if (interval.getIntervalUnit() == AdvertisementIntervalUnit.SECOND){
				hourMinutes = (interval.getInterval() * 1000);
				minutes = Duration.between(advertisement.getBeginTime(), LocalDateTime.now()).toMillis();
			}
			if (minutes >= hourMinutes) {
				advertisement.setBeginTime(LocalDateTime.now());
				advertisementCache.put(cacheId, advertisement);
				return true;
			}
			return false;
		}
	}
}